using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WHLRDF.ORM
{
	/// <summary>
	/// An <see cref="ICriterion"/> that constrains the property
	/// to a specified list of values.
	/// </summary>
	/// <remarks>
	/// InExpression - should only be used with a Single Value column - no multicolumn properties...
	/// </remarks>
	[Serializable]
	public class InExpression : AbstractCriterion
	{
		private readonly IProjection _projection;
		private readonly string _propertyName;
		private object[] _values;
		private string _op;

		/// <summary>
		/// Initializes a new instance of the <see cref="InExpression"/> class.
		/// </summary>
		/// <param name="projection">The projection.</param>
		/// <param name="values">The _values.</param>
		public InExpression(IProjection projection, object[] values,string op="in")
		{
			_projection = projection;
			_values = values;
			_op = op;
		}

		public InExpression(string propertyName, object[] values, string op = "in")
		{
			_propertyName = propertyName;
			_values = values;
			_op = op;
		}

		public override IProjection[] GetProjections()
		{
			if (_projection != null)
			{
				return new IProjection[] { _projection };
			}
			return null;
		}

		public override SqlString ToSqlString(ICriteria criteria, ICriteriaQuery criteriaQuery)
		{
			if (_projection == null)
			{
				//AssertPropertyIsNotCollection(criteriaQuery, criteria);
			}

			if (_values.Length == 0)
			{
				// "something in ()" is always false
				return new SqlString("1=0");
			}

			//TODO: add default capacity
			SqlStringBuilder result = new SqlStringBuilder();
			//SqlString[] columnNames =
			//	CriterionUtil.GetColumnNames(_propertyName, _projection, criteriaQuery, criteria);
			
			//// Generate SqlString of the form:
			//// columnName1 in (values) and columnName2 in (values) and ...
			//Parameter[] parameters = GetParameterTypedValues(criteria, criteriaQuery).SelectMany(t => criteriaQuery.NewQueryParameter(t)).ToArray();

			//for (int columnIndex = 0; columnIndex < columnNames.Length; columnIndex++)
			//{
			//	SqlString columnName = columnNames[columnIndex];

			//	if (columnIndex > 0)
			//	{
			//		result.Add(" and ");
			//	}

			//	result
			//		.Add(columnName)
			//		.Add(" in (");

			//	for (int i = 0; i < _values.Length; i++)
			//	{
			//		if (i > 0)
			//		{
			//			result.Add(StringHelper.CommaSpace);
			//		}
			//		result.Add(parameters[i]);
			//	}

			//	result.Add(")");
			//}

			return result.ToSqlString();
		}

		public object[] Values
		{
			get { return _values; }
			protected set { _values = value; }
		}

        public override string ToString()
        {
            return (_projection ?? (object)_propertyName) + " "+_op+" (" +StringHelper.ToString(_values) + ')';
        }
        public override string ToString(ref DataParameterCollection dataParam, bool isNameParams = false)
        {
            string propertyName = _propertyName;
            StringBuilder strWhere = new StringBuilder("");
            if (_values != null)
            {
                strWhere.Append(_propertyName + " " + _op + " (");
                for (int i = 0; i < _values.Length; i++)
                {
                    propertyName = _propertyName + i.ToString();
                    dataParam.Add(new DataParameter(propertyName, _values[i]), ref propertyName);
                    if (i > 0)
                    {
                        strWhere.Append(",");
                    }
                    strWhere.Append(dataParam.GetParameter(propertyName));
                }
                strWhere.Append(")");
            }
            return strWhere.ToString();
        }

    }
}
